package ads1ss09.pa1;

import java.io.FileInputStream;

import ads1ss09.pa1.InputScanner;
import ads1ss09.pa1.ThreadedBinaryTree;
import ads1ss09.pa1.ThreadedBinaryTree.ThreadedBinaryTreeNode;

public class UtilStuff {

	private final InputScanner scanner;

	private final ThreadedBinaryTree tree = new ThreadedBinaryTree();

	private int size;
	
	public static ThreadedBinaryTree newDefaultTree() {
		final ThreadedBinaryTree tree = new ThreadedBinaryTree();
		
		tree.insert(100);
		tree.insert(20);
		tree.insert(10);
		tree.insert(90);
		tree.insert(30);
		tree.insert(50);
		tree.insert(40);
		tree.insert(60);
		tree.insert(70);
		
		return tree;
	}
	
	/**
	 * @return "OK <pre> <post>"
	 */
	public static String processFile(String fileName) { // e.g.: "test/input/0000"
		try {
			final UtilStuff test = new UtilStuff(fileName);
			test.run();
			return "OK " + test.getPreorder() + " " + test.getPostorder();
			
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public UtilStuff(String fileName) throws Exception {
		this.scanner = new InputScanner(new FileInputStream(fileName)); 
	}

	public void run() throws Exception {
		int v = -1;
		while (scanner.nextValue()) {
			v = scanner.getValue();
			processInput(scanner.getType(), v);
		}
		
		this.tree.testSearchTree();
		this.tree.checkLtr();
		this.tree.checkRtl();
	}
	
	public ThreadedBinaryTree getTree() {
		return this.tree;
	}
	
	public String getPreorder() {
		return this.tree.preorder(this.size);
	}
	
	public String getPostorder() {
		return this.tree.postorder(this.size);
	}
	
	private void processInput(InputScanner.ValueType type, int value) throws Exception {
		switch (scanner.getType()) {
		case INVALID:
			throw new Exception("Invalid scanner access");
		case INSERT:
			// System.err.println("INSERT " + value);
			tree.insert(value);
			size++;

			break;
		case REMOVE:
			throw new RuntimeException("input may not contain the #remove directive");
			// System.err.println("REMOVE " + value);

		case FIND:
			// System.err.println("FIND " + value);
			tree.find(value);

			break;
		default:
			throw new RuntimeException("This should be unreachable");
		}
	}

	public static boolean areEquals(ThreadedBinaryTreeNode r1, Node r2) {
		if(r1.getKey() != r2.key) {
			return false;
		}

		if(r1.getLeft() != null && r1.leftIsThread() == false &&
		   r2.left != null) {
			areEquals(r1.getLeft(), r2.left);
		} else {
			return false;
		}

		if(r1.getRight() != null && r1.rightIsThread() == false &&
		   r2.right != null) {
			areEquals(r1.getRight(), r2.right);
		} else {
			return false;
		}
		
		return true;
	}
}
